﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using Frogism.Core;
namespace Frogism.Core {
  public class Account : ObjectNameBase, IAccount {

    public virtual decimal ToGo {
      get {
        return (NextGoalValue - Balance);
      }
    }
    public virtual decimal Balance
    {
      get {
        return Transactions.Sum(t=>t.Value);
      }
    }
    public virtual decimal ConfirmedBalance
    {
      get {
        // return Transactions.Where(a => a.IsConfirmed).Sum(a => a.Amount);
        return (
                from transaction in Transactions
                where transaction.IsConfirmed
                select transaction.Value
                ).Sum();
      }
    }

    private ICollection<ITransaction> _transactions;
    public virtual ICollection<ITransaction> Transactions
    {
      get {
          if (_transactions == null)
          {
              _transactions = new Collection<ITransaction>();
        }
          return _transactions;
      }
    }
    /*
    public Frogism.Core.IAccountType AccountType {
      get;
      set;
    }
     */



    #region IAccount Members


    public virtual decimal LastMonth
    {
      get {
        DateTime d = DateTime.Now.AddMonths(-1);

        return (from transaction in Transactions
                   where transaction.TransactionDate <= d.EndOfMonth()
                select transaction.Value).Sum();
        ;
      }
    }

    #endregion

    public virtual decimal RemainingPercent
    {
        get
        {
            if (AccountType == DBConst.AccountTypeMortgage)
            {
                return Math.Round(Balance / MaxValue*100m,2);
            }
            else
            {
                return 0;
            }
        }
    }
    #region IAccount Members


    /// <summary>
    /// if a payment, deposite or transfer isn't confirmed then it 
    /// does not count on remaining
    /// </summary>
    public virtual decimal Remaining
    {
      get {
        decimal balance = (from transaction in Transactions
                               where transaction.IsConfirmed ||
                                   transaction.TransactionType.Value == DBConst.TransactionTypeExpense
                                   || transaction.TransactionType.Value == DBConst.TransactionTypeBill
                               select transaction.Value
                  ).Sum();
        if (AccountType == DBConst.AccountTypeCreditCard) //debit
        {
            return ((-1 * MinValue) + balance);
        }
        else if (AccountType == DBConst.AccountTypeMortgage)
        {
            return MaxValue - balance;
        }
        else
        {
            return balance;
        }
      }
    }

    #endregion

    public virtual void SetTransactions(IList<ITransaction> transactions)
    {
        this._transactions = transactions;
   }

   public virtual decimal Change
   {
      get {
        return this.Balance - this.LastMonth;
      }
    }


   public virtual decimal YearStart
   {
      get {
        DateTime d = DateTime.Now;
        return (from transaction in Transactions
                   where transaction.TransactionDate.Year < d.Year
                   select transaction.Value).Sum();
      }
    }

    public static DateTime BUDGET_START_DATE = new DateTime(2007, 11, 1, 0, 0, 0);

    public virtual decimal Start
    {
      get {
   
        return (from transaction in Transactions
                   where transaction.TransactionDate < BUDGET_START_DATE
                   select transaction.Value).Sum();
      }
    }


    public virtual int AccountType
    {
      get;
      set;
    }

    public virtual bool IsActive
    {
      get;
      set;
    }

    public virtual decimal MaxValue
    {
      get;
      set;
    }

    public virtual decimal MinValue
    {
      get;
      set;
    }

    public virtual decimal NextGoalValue
    {
      get;
      set;
    }

    public virtual string Purpose
    {
      get;
      set;
    }
  }
}
